package com.lezhu.plugins;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PermissionHelper;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.idcard.CardInfo;
import com.idcard.TFieldID;
import com.idcard.TParam;
import com.idcard.TRECAPIImpl;
import com.idcard.TStatus;
import com.idcard.TengineID;
import com.turui.bank.ocr.CaptureActivity;
import com.ui.card.TRCardScan;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;

/**
 * 各种卡片识别：身份证识别、银行卡识别等
 *
 * @sa https://github.com/apache/cordova-android/blob/master/framework/src/org/apache/cordova/CordovaPlugin.java
 */
public class CardScanner extends CordovaPlugin {
	/** 银行卡 */
	public int REQUEST_NUM = 2;
	/** 个人证件信息 */
	public int REQUEST_CARD = 1;
	/** 银行卡成功返回 */
	public int RESULT_GET_OK = 1;
	/** 个人证件信息成功返回 */
	public int RESULT_GET_ERROR = 2;
	
	private TengineID tengineID = TengineID.TIDCARD2;
	private TRECAPIImpl engineDemo = new TRECAPIImpl();
	

    private static final String LOG_TAG = "CardScanner";
    private String [] permissions = { Manifest.permission.CAMERA };

    private JSONArray requestArgs;
    private CallbackContext callbackContext;

    /**
     * Constructor.
     */
    public CardScanner() {
    }

    /**
     * Executes the request.
     *
     * This method is called from the WebView thread. To do a non-trivial amount of work, use:
     *     cordova.getThreadPool().execute(runnable);
     *
     * To run on the UI thread, use:
     *     cordova.getActivity().runOnUiThread(runnable);
     *
     * @param action          The action to execute.
     * @param args            The exec() arguments.
     * @param callbackContext The callback context used when calling back into JavaScript.
     * @return                Whether the action was valid.
     *
     * @sa https://github.com/apache/cordova-android/blob/master/framework/src/org/apache/cordova/CordovaPlugin.java
     */
    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) {
        this.callbackContext = callbackContext;
        this.requestArgs = args;

        if (action.equals("init")) {
            TStatus tStatus = engineDemo.TR_StartUP();
    		if (tStatus == TStatus.TR_TIME_OUT ) {
    			callbackContext.error("识别引擎过期");
    		} else  if (tStatus == TStatus.TR_FAIL) {
    			callbackContext.error("识别引擎初始化失败");
    		} else {
          Log.i(LOG_TAG, "----身份证识别引擎初始化成功！");
    			callbackContext.success("识别引擎初始化成功");
    		}
        } else if (action.equals("scan")) {
            //android permission auto add
            if(!hasPermisssion()) {
              requestPermissions(0);
            } else {
              scan(args);
            }
        } else {
            return false;
        }
        return true;
    }

    /**
     * 开始扫描证件
     */
    public void scan(final JSONArray args) {
        final CordovaPlugin that = this;
        cordova.getThreadPool().execute(new Runnable() {
            public void run() {
            	int requestCode = REQUEST_CARD; //缺省读取个人证件信息
            	JSONObject obj = args.optJSONObject(0);
            	int type = obj.optInt("type");
            	boolean openLight = obj.optBoolean("light", false);
            	CaptureActivity.ShowCopyRightTxt = "";
            	if (type == 1) { //身份证二代证
            		engineDemo.TR_SetParam(TParam.T_SET_HEADIMG, 1);
            		CaptureActivity.tengineID = TengineID.TIDCARD2;
                	tengineID = TengineID.TIDCARD2;
            	} else if (type == 2) { //驾驶证
            		CaptureActivity.tengineID = TengineID.TIDJSZCARD;
					tengineID = TengineID.TIDJSZCARD;
				} else if (type == 3) { //行驶证
					CaptureActivity.tengineID = TengineID.TIDXSZCARD;
					tengineID = TengineID.TIDXSZCARD;
				} else if (type == 4) { //银行卡
					CaptureActivity.tengineID = TengineID.TIDBANK;
					tengineID = TengineID.TIDBANK;
					requestCode = REQUEST_NUM;
				} else if (type == 5) { //车牌
					CaptureActivity.tengineID = TengineID.TIDLPR;
					tengineID = TengineID.TIDLPR;
					requestCode = REQUEST_NUM;
				} else { //缺省身份证二代证
					engineDemo.TR_SetParam(TParam.T_SET_HEADIMG, 1);
					CaptureActivity.tengineID = TengineID.TIDCARD2;
                	tengineID = TengineID.TIDCARD2;
				}
            	CaptureActivity.SetDisplayLight(openLight);
            	CaptureActivity.SetShowBackBotton(true);
            	Intent intent = new Intent(that.cordova.getActivity().getApplicationContext(), CaptureActivity.class);
            	intent.putExtra("engine", engineDemo);
            	that.cordova.startActivityForResult(that, intent, requestCode);
            }
        });
    }

    /**
     * Called when the barcode scanner intent completes.
     *
     * @param requestCode The request code originally supplied to startActivityForResult(),
     *                       allowing you to identify who this result came from.
     * @param resultCode  The integer result code returned by the child activity through its setResult().
     * @param intent      An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
     */
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
    	Log.d(LOG_TAG, "==========resultCode:" + resultCode + "  requestCode:" + requestCode);
    	if (this.callbackContext != null) {
    		JSONObject obj = new JSONObject();
    		if (requestCode == REQUEST_CARD) {
    			if (resultCode == RESULT_GET_OK) {
                	Log.d(LOG_TAG, "==========resultCode:" + resultCode + "  requestCode:" + requestCode);
        			// 处理身份证识别信息（在界面上显示）
        			CardInfo cardInfo = (CardInfo) intent.getSerializableExtra("cardinfo");


        			try {
        				//处理身份证信息
        				obj.put("name", cardInfo.getFieldString(TFieldID.NAME));
        				if (cardInfo.getFieldString(TFieldID.NAME).isEmpty()) {
        					this.callbackContext.error("no shot,only return clicked");
        				} else {
            				obj.put("sex", cardInfo.getFieldString(TFieldID.SEX));
            				obj.put("folk", cardInfo.getFieldString(TFieldID.FOLK));
            				obj.put("birthday", cardInfo.getFieldString(TFieldID.BIRTHDAY));
            				obj.put("address", cardInfo.getFieldString(TFieldID.ADDRESS));
            				obj.put("num", cardInfo.getFieldString(TFieldID.NUM));
            				obj.put("issue", cardInfo.getFieldString(TFieldID.ISSUE));
            				obj.put("period", cardInfo.getFieldString(TFieldID.PERIOD));
            				
                			//身份证正面时， 能获取到人头像图片
                			Bitmap headimg = CaptureActivity.SmallBitmap;// 人头像
                			Bitmap Takeimg = CaptureActivity.TakeBitmap;  // 全图
            				if (headimg != null) {
            					obj.put("headImage", saveFile(headimg, "headimg.jpg"));
            				}
            				if (Takeimg != null) {
            					obj.put("takeImage", saveFile(Takeimg, "takeimg.jpg"));
            				}
            				this.callbackContext.success(obj);
        				}
        			} catch(JSONException e) {
        				Log.d(LOG_TAG, "This should never happen");
        				this.callbackContext.error("shot error:" + e.getMessage());
        			}
    			} else {
    				this.callbackContext.error("no shot,only return clicked");
    			}
            } else if (requestCode == REQUEST_NUM) {
            	if (resultCode == RESULT_GET_OK) {
            		Bundle bundle = intent.getExtras();
        			String result = bundle.getString("result");
        			Bitmap small = CaptureActivity.SmallBitmap;//号码截图
        			Bitmap takeimg = CaptureActivity.TakeBitmap;// 全图
                    try {
                    	Log.d(LOG_TAG, "==========info:" + result);
                        obj.put("info", result);
                    } catch (JSONException e) {
                        Log.d(LOG_TAG, "This should never happen");
                    }
            		this.callbackContext.success(obj);
    			} else {
    				this.callbackContext.error("no shot,only return clicked");
    			}
            } else {
            	this.callbackContext.error("invalid request code");
            }
    	}
        
    }
    
    /**  
    * 将Bitmap转换成文件
     * 保存文件  
     * @param bm  
     * @param fileName  
     * @throws IOException  
     */    
    private String saveFile(Bitmap bm, String fileName) {
    	String filePath = "";
    	try {
        	String path = getTempDirectoryPath();
            File dirFile = new File(path);    
            if(!dirFile.exists()){    
                dirFile.mkdir();    
            }    
            File myCaptureFile = new File(path , fileName);    
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(myCaptureFile));    
            bm.compress(Bitmap.CompressFormat.JPEG, 80, bos);    
            bos.flush();    
            bos.close();
            filePath = myCaptureFile.getAbsolutePath();
    	} catch(IOException e) {
    		Log.e(LOG_TAG, "save ID CARD image failed: " + e.getMessage());
    	}
        return filePath;
    }
    
    private String getTempDirectoryPath() {
        File cache = null;

        // SD Card Mounted
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            cache = cordova.getActivity().getExternalCacheDir();
        }
        // Use internal storage
        else {
            cache = cordova.getActivity().getCacheDir();
        }

        // Create the cache directory if it doesn't exist
        cache.mkdirs();
        return cache.getAbsolutePath();
    }

    /**
     * The final call you receive before your activity is destroyed.
     */
    public void onDestroy() {
    	engineDemo.TR_ClearUP();
    	super.onDestroy();
    }
    
    /**
     * check application's permissions
     */
   public boolean hasPermisssion() {
       for(String p : permissions)
       {
           if(!PermissionHelper.hasPermission(this, p))
           {
               return false;
           }
       }
       return true;
   }

    /**
     * We override this so that we can access the permissions variable, which no longer exists in
     * the parent class, since we can't initialize it reliably in the constructor!
     *
     * @param requestCode The code to get request action
     */
   public void requestPermissions(int requestCode)
   {
       PermissionHelper.requestPermissions(this, requestCode, permissions);
   }

   /**
   * processes the result of permission request
   *
   * @param requestCode The code to get request action
   * @param permissions The collection of permissions
   * @param grantResults The result of grant
   */
  public void onRequestPermissionResult(int requestCode, String[] permissions,
                                         int[] grantResults) throws JSONException
   {
       PluginResult result;
       for (int r : grantResults) {
           if (r == PackageManager.PERMISSION_DENIED) {
               Log.d(LOG_TAG, "Permission Denied!");
               result = new PluginResult(PluginResult.Status.ILLEGAL_ACCESS_EXCEPTION);
               this.callbackContext.sendPluginResult(result);
               return;
           }
       }

       switch(requestCode)
       {
           case 0:
               scan(this.requestArgs);
               break;
       }
   }

}
